package com.yunyang.jczd.facade.fileexport.service.impl;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.yunyang.jczd.base.file.fileexport.dto.JczdExportRecordDTO;
import com.yunyang.jczd.business.response.PageResult;
import com.yunyang.jczd.business.response.Response;
import com.yunyang.jczd.business.response.ResponseUtils;
import com.yunyang.jczd.business.web.current.RequestContext;
import com.yunyang.jczd.businessline.civil.dto.JczdFamilyFinancialSituationDTO;
import com.yunyang.jczd.businessline.help.criteria.SearchDifficultCommunistVisitCriteria;
import com.yunyang.jczd.businessline.help.dto.JczdDifficultCommunistVisitRecordDTO;
import com.yunyang.jczd.enums.ExportFileTypeEnum;
import com.yunyang.jczd.enums.ExportStateEnum;
import com.yunyang.jczd.enums.ExportTypeEnum;
import com.yunyang.jczd.facade.fileexport.entity.ExportConfig;
import com.yunyang.jczd.facade.fileexport.mapper.ExportConfigMapper;
import com.yunyang.jczd.facade.fileexport.service.IExportService;
import com.yunyang.jczd.facade.fileexport.service.IJczdExportRecordService;
import com.yunyang.jczd.foundation.core.common.helpers.CollectionHelper;
import com.yunyang.jczd.foundation.core.common.helpers.ExcelHelp;
import com.yunyang.jczd.web.common.JczdHeaders;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * <p>
 * 导出配置，目前默认excel 服务实现类
 * </p>
 *
 * @author kerns
 * @since 2020-12-17
 */
@Service
@Slf4j
public class ExportServiceImpl implements IExportService {

    private RestTemplate restTemplate;

    private IJczdExportRecordService exportRecordService;

    private WeakHashMap<String, Class> weakHashMap = new WeakHashMap(50);

    public ExportServiceImpl(RestTemplate restTemplate, IJczdExportRecordService exportRecordService) {
        this.restTemplate = restTemplate;
        this.exportRecordService = exportRecordService;
    }

    @Override
    public Response tryRequest(HttpHeaders httpHeaders, Map<String, Object> param, ExportConfig exportConfig) {
        Response response = null;
        if (Objects.equals(MediaType.APPLICATION_JSON, httpHeaders.getContentType())) {
            HttpEntity httpEntity = new HttpEntity(JSON.toJSONString(param), httpHeaders);
            //这个当时从数据库里面获取
            response = restTemplate.postForObject(exportConfig.getDataRequestUrl(), httpEntity, Response.class);
        } else if (Objects.equals(MediaType.APPLICATION_FORM_URLENCODED, httpHeaders.getContentType())) {
            HttpEntity httpEntity = new HttpEntity(param, httpHeaders);
            //这个当时从数据库里面获取
            response = restTemplate.postForObject(exportConfig.getDataRequestUrl(), httpEntity, Response.class);
        } else {
            return ResponseUtils.fail("不支持的请求方式");
        }
        if (!ResponseUtils.isSuccess(response)) {
            return ResponseUtils.fail(response.getCode(), response.getMessage());
        }
        return ResponseUtils.success(response.getData());
    }

    @Override
    @Async
    public void export(HttpHeaders httpHeaders, Map<String, Object> param, ExportConfig exportConfig) {
        JczdExportRecordDTO exportRecord = exportRecordService.saveExport(ExportFileTypeEnum.EXCEl.getCode(), exportConfig.getId());
        if (Objects.equals(MediaType.APPLICATION_JSON, httpHeaders.getContentType())) {
            if (exportConfig.getDataRequestFrequency() == 2) {
                exportPage(httpHeaders, param, exportRecord, exportConfig);
            }
        }
    }

    private void exportPage(HttpHeaders headers, Map<String, Object> param, JczdExportRecordDTO exportRecord, ExportConfig exportConfig) {
        ExcelWriter excelWriter = null;
        boolean success = true;
        try {
            excelWriter = ExcelHelp.getExcelWriter("/Users/apple/Documents/yunyang/jczd-facade/tt.xlsx", getCacheClass(exportConfig.getExportClass()));
            WriteSheet writeSheet = ExcelHelp.getWriteSheet(exportConfig.getRemark());
            Integer total = Integer.MAX_VALUE;
            Integer currentTotal = 0;
            Integer page = 1;
            while (currentTotal < total) {
                param.put("page", page);
                param.put("size", ExcelHelp.DEFAULT_SIZE);
                HttpEntity httpEntity = new HttpEntity(JSON.toJSONString(param), headers);
                Response response = restTemplate.postForObject(exportConfig.getDataRequestUrl(), httpEntity, Response.class);
                if (!ResponseUtils.isSuccess(response)) {
                    success = false;
                    break;
                }
                Map pageResult = (Map) response.getData();
                List data = (List) pageResult.get("results");
                List objs = JSON.parseArray(JSON.toJSONString(data), getCacheClass(exportConfig.getExportClass()));
                if (CollectionHelper.isEmpty(data)) {
                    if (page == 1) {
                        excelWriter.write(data, writeSheet);
                    }
                    break;
                }
                excelWriter.write(objs, writeSheet);
                page++;
                total = (Integer) pageResult.get("itemCount");
                currentTotal = currentTotal + ExcelHelp.DEFAULT_SIZE;
            }
        } catch (Exception ex) {
            success = false;
            log.error("导出excel异常", ex);
        } finally {
            closExcelWriter(excelWriter, success, exportRecord);
        }
    }

    private Class<?> getCacheClass(String className) throws ClassNotFoundException {
        Class<?> clz = weakHashMap.get(className);
        if (clz == null) {
            clz = Class.forName(className);
            weakHashMap.put(className, clz);
        }
        return clz;
    }

    public void closExcelWriter(ExcelWriter excelWriter, boolean issuccess, JczdExportRecordDTO export) {
        try {
            RequestContext.clear();
            if (excelWriter != null) {
                excelWriter.finish();
            }
        } catch (Exception e) {
            issuccess = false;
            log.error("关闭excel流异常", e);
        }
        if (Objects.nonNull(export)) {
            exportRecordService.updateExportState(export.getId(), issuccess ? ExportStateEnum.SUCCESS.getCode() : ExportStateEnum.FAIL.getCode());
        }
    }

}